/*
 * @description: 
 * @Author: T.W
 * @Github: https://github.com/TernenceWu0702
 * @Date: 2021-07-27 14:15:21
 * @LastEditors: T.W
 * @LastEditTime: 2021-07-27 14:37:47
 */

export const EventEmitter = class _EventEmitter {
    [x: string]: {}

    constructor() {
        this.subs = {}
    }

    /**
     * @description: 为指定事件注册一个监听器，接受一个事件名称 eventName 和一个回调监听器函数 listener。
     * @param {string} eventName 事件名称
     * @param {Function} listener 监听器函数
     */
    on(eventName: string, listener: Function) {
        (this.subs[eventName] || (this.subs[eventName] = [])).push(listener)
    }


    /**
     * 为指定事件注册一个单次监听器，即 监听器最多只会触发一次，触发后立刻解除该监听器。
     * @param eventName 事件名称
     * @param listener 监听器函数
     */
    once(eventName: string, listener: Function) {
        const listenerCb = (...args) => {
            listener(args)
            this.off(eventName, listener)
        }
        this.on(eventName, listenerCb)
    }

    /**
     * @description: 触发指定事件的监听器
     * @param {string} eventName 事件名称
     * @param {...array} args 传入监听器函数的参数
     */
    emit(eventName: string, ...args) {
        this.subs[eventName] && this.subs[eventName].forEach(listener => {
            listener(args)
        })
    }

    /**
     * 移除指定事件的某个监听器，监听器必须是该事件已经注册过的监听器。
     * @param eventName 事件名称
     * @param listener 监听器函数
     */
    off(eventName: string, listener: Function) {
        if (this.subs[eventName]) {
            const index = this.subs[eventName].findIndex(cb => cb === listener)
            this.subs[eventName].splice(index, 1)
            if (!this.subs[eventName].length) delete this.subs[eventName]
        }
    }

    /**
     * 移除所有事件的所有监听器， 如果指定事件，则移除指定事件的所有监听器。
     * @param eventName 事件名称
     */
    allOff(eventName: string) {
        if (eventName && this.subs[eventName]) {
            delete this.subs[eventName]
        } else {
            this.subs = {}
        }
    }

}